<p>This rule raises an issue when the code cognitive complexity of a function is above a certain threshold.</p>
<h2>Why is this an issue?</h2>
<p>Cognitive Complexity is a measure of how hard it is to understand the control flow of a unit of code. Code with high cognitive complexity is hard
to read, understand, test, and modify.</p>
<p>As a rule of thumb, high cognitive complexity is a sign that the code should be refactored into smaller, easier-to-manage pieces.</p>
<h3>Which syntax in code does impact cognitive complexity score?</h3>
<p>Here are the core concepts:</p>
<ul>
  <li> <strong>Cognitive complexity is incremented each time the code breaks the normal linear reading flow.</strong><br> This concerns, for example,
  loop structures, conditionals, catches, switches, jumps to labels, and conditions mixing multiple operators. </li>
  <li> <strong>Each nesting level increases complexity.</strong><br> During code reading, the deeper you go through nested layers, the harder it
  becomes to keep the context in mind. </li>
  <li> <strong>Method calls are free</strong><br> A well-picked method name is a summary of multiple lines of code. A reader can first explore a
  high-level view of what the code is performing then go deeper and deeper by looking at called functions content.<br> <em>Note:</em> This does not
  apply to recursive calls, those will increment cognitive score. </li>
</ul>
<p>The method of computation is fully detailed in the pdf linked in the resources.</p>
<h3>Exceptions</h3>
<p><code>equals</code> and <code>hashCode</code> methods are ignored because they might be automatically generated and might end up being difficult to
understand, especially in the presence of many fields.</p>
<h2>How to fix it</h2>
<p>Reducing cognitive complexity can be challenging.<br> Here are a few suggestions:</p>
<ul>
  <li> <strong>Extract complex conditions in a new function.</strong><br> Mixed operators in condition will increase complexity. Extracting the
  condition in a new function with an appropriate name will reduce cognitive load. </li>
  <li> <strong>Break down large functions.</strong><br> Large functions can be hard to understand and maintain. If a function is doing too many
  things, consider breaking it down into smaller, more manageable functions. Each function should have a single responsibility. </li>
  <li> <strong>Avoid deep nesting by returning early.</strong><br> To avoid the nesting of conditions, process exceptional cases first and return
  early. </li>
</ul>
<h3>Code examples</h3>
<p><strong>Extraction of a complex condition in a new function.</strong></p>
<h4>Noncompliant code example</h4>
<p>The code is using a complex condition and has a cognitive cost of 3.</p>
<pre data-diff-id="1" data-diff-type="noncompliant">
double calculateFinalPrice(User user, Cart cart) {
  double total = calculateTotal(cart);
  if (user.hasMembership()                            // +1 (if)
    &amp;&amp; user.ordersCount() &gt; 10                        // +1 (more than one condition)
    &amp;&amp; user.isAccountActive()
    &amp;&amp; !user.hasDiscount()
    || user.ordersCount() == 1) {                    // +1 (change of operator in condition)
    total = applyDiscount(user, total);
  }
  return total;
}
</pre>
<h4>Compliant solution</h4>
<p>Even if the cognitive complexity of the whole program did not change, it is easier for a reader to understand the code of the
<code>calculateFinalPrice</code> function, which now only has a cognitive cost of 1.</p>
<pre data-diff-id="1" data-diff-type="compliant">
double calculateFinalPrice(User user, Cart cart) {
  double total = calculateTotal(cart);
  if (isEligibleForDiscount(user)) {                  // +1 (if)
    total = applyDiscount(user, total);
  }
  return total;
}

boolean isEligibleForDiscount(User user) {
  return user.hasMembership()
    &amp;&amp; user.ordersCount() &gt; 10                        // +1 (more than one condition)
    &amp;&amp; user.isAccountActive()
    &amp;&amp; !user.hasDiscount()
    || user.ordersCount() == 1;                       // +1 (change of operator in condition)
}
</pre>
<p><strong>Break down large functions.</strong></p>
<h4>Noncompliant code example</h4>
<p>For example, consider a function that calculates the total price of a shopping cart, including sales tax and shipping.<br> <em>Note:</em> The code
is simplified here, to illustrate the purpose. Please imagine there is more happening in the <code>for</code> loops.</p>
<pre data-diff-id="2" data-diff-type="noncompliant">
double calculateTotal(Cart cart) {
  double total = 0;
  for (Item item : cart.items()) {       // +1 (for)
    total += item.price;
  }

  // calculateSalesTax
  for (Item item : cart.items()) {       // +1 (for)
    total += 0.2 * item.price;
  }

  //calculateShipping
  total += 5 * cart.items().size();

  return total;
}
</pre>
<p>This function could be refactored into smaller functions: The complexity is spread over multiple functions and the complex
<code>calculateTotal</code> has now a complexity score of zero.</p>
<h4>Compliant solution</h4>
<pre data-diff-id="2" data-diff-type="compliant">
double calculateTotal(Cart cart) {
  double total = 0;
  total = calculateSubtotal(cart, total);
  total += calculateSalesTax(cart, total);
  total += calculateShipping(cart, total);

  return total;
}

double calculateShipping(Cart cart, double total) {
  total += 5 * cart.items().size();
  return total;
}

double calculateSalesTax(Cart cart, double total) {
  for (Item item : cart.items()) {       // +1 (for)
    total += 0.2 * item.price;
  }
  return total;
}

double calculateSubtotal(Cart cart, double total) {
  for (Item item : cart.items()) {       // +1 (for)
    total += item.price;
  }
  return total;
}
</pre>
<p><strong>Avoid deep nesting by returning early.</strong></p>
<h4>Noncompliant code example</h4>
<p>The below code has a cognitive complexity of 6.</p>
<pre data-diff-id="3" data-diff-type="noncompliant">
double calculateDiscount(double price, User user) {
  if (isEligibleForDiscount(user)) {      // +1 ( if )
    if (user.hasMembership()) {           // +2 ( nested if )
      return price * 0.9;
    } else if (user.ordersCount() == 1) { // +1 ( else )
      return price * 0.95;
    } else {                              // +1 ( else )
      return price;
    }
  } else {                                // +1 ( else )
    return price;
  }
}
</pre>
<h4>Compliant solution</h4>
<p>Checking for the edge case first flattens the <code>if</code> statements and reduces the cognitive complexity to 3.</p>
<pre data-diff-id="3" data-diff-type="compliant">
double calculateDiscount(double price, User user) {
  if (!isEligibleForDiscount(user)) {     // +1 ( if )
    return price;
  }
  if (user.hasMembership()) {             // +1
    return price * 0.9;
  }
  if (user.ordersCount() == 1) {          // +1 ( if )
    return price * 0.95;
  }
  return price;
}
</pre>
<h3>Pitfalls</h3>
<p>As this code is complex, ensure that you have unit tests that cover the code before refactoring.</p>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
  <li> Sonar - <a href="https://www.sonarsource.com/docs/CognitiveComplexity.pdf">Cognitive Complexity</a> </li>
</ul>
<h3>Articles &amp; blog posts</h3>
<ul>
  <li> Sonar Blog - <a href="https://www.sonarsource.com/blog/5-clean-code-tips-for-reducing-cognitive-complexity/">5 Clean Code Tips for Reducing
  Cognitive Complexity</a> </li>
</ul>

